package loginuser

import (
	"encoding/json"
	"os"
	"strings"

	"gitee.com/tomatomeatman/golang-repository/bricks3/function/configutil"
	"gitee.com/tomatomeatman/golang-repository/bricks3/function/data/base64util"
	"gitee.com/tomatomeatman/golang-repository/bricks3/function/data/md5util"
	"gitee.com/tomatomeatman/golang-repository/bricks3/model/dbinfo"
	"gitee.com/tomatomeatman/golang-repository/bricks3/model/globalvariable"
	"gitee.com/tomatomeatman/golang-repository/bricks3/utils/app/common"
	"gitee.com/tomatomeatman/golang-repository/bricks3/utils/app/moduleutil"
	"gitee.com/tomatomeatman/golang-repository/bricks3/utils/sqlfactory"
	Log "github.com/cihub/seelog"
	"github.com/gin-gonic/gin"
)

/**
 * 初始化
 */
func init() {
	globalvariable.Add("Module@LoginUserService", &LoginUserService{})
}

/**
 * 用户表LoginUser表基本业务操作结构体
 */
type LoginUserService struct {
}

/**
 * 新增
 * @param ctx Http请求对象
 * @param dbEntity 实体数据结构
 * @param params 数据
 * @return *msgentity.MsgEntity 返回执行结果
 */
func (service LoginUserService) Add(ctx *gin.Context, params map[string]interface{}) (bool, string, interface{}) {
	No, ok := params["No"]
	if !ok || (strings.TrimSpace(No.(string)) == "") {
		return false, "工号作为唯一标识不能为空!", 8401 //在同一根部门下,工号必须唯一
	}

	Name, ok := params["Name"]
	if !ok || (strings.TrimSpace(Name.(string)) == "") {
		return false, "用户名称不能为空!", 8402 //在同一根部门下,工号必须唯一
	}

	temp := strings.ToLower(strings.TrimSpace(No.(string)))
	if (temp == "admin") || (temp == "superadmin") {
		return false, "特殊标识,禁止使用!", 8403
	}

	temp = strings.ToLower(strings.TrimSpace(Name.(string)))
	if (temp == "admin") || (temp == "superadmin") {
		return false, "特殊名称,禁止使用!", 8404
	}

	Pass, ok := params["pass"]
	if !ok || (strings.TrimSpace(Pass.(string)) == "") {
		return false, "密码不能为空!", 8405
	}

	appMd5Key := configutil.ReadConfigKey("", "App", "Md5Key", "555").(string)
	params["pass"] = md5util.Lower(Pass, appMd5Key)

	// Owner, ok := params["owner"]
	// if !ok || (strings.TrimSpace(Owner.(string)) == "") {
	// 	params["owner"] = "BaseSystem.LoginUser"
	// }

	loginUserBusinessInfo := GetLoginUserBusinessInfo()
	bl, msg, data := sqlfactory.AnalysisEntity(loginUserBusinessInfo.DbName, loginUserBusinessInfo.TableName)
	if !bl {
		return bl, msg, data
	}

	refer := data.(*dbinfo.TableInfo)

	return common.GetService(loginUserBusinessInfo.DbName, loginUserBusinessInfo.TableName).Add(ctx, refer, params)
}

/**
 * 修改
 * @param entity 对象类型
 * @param id 记录编号值
 * @param iVersion 记录版本号
 * @param data 待更新的字段和值
 * @return *msgentity.MsgEntity 返回执行结果
 */
func (service LoginUserService) Edit(ctx *gin.Context, refer *dbinfo.TableInfo, id interface{}, iVersion int, data map[string]interface{}) (bool, string, interface{}) {
	No, ok := data["No"]
	if ok && (strings.TrimSpace(No.(string)) == "") {
		return false, "工号作为唯一标识不能为空!", 8401 //在同一根部门下,工号必须唯一
	}

	if ok {
		temp := strings.ToLower(strings.TrimSpace(No.(string)))
		if (temp == "admin") || (temp == "superadmin") {
			return false, "特殊标识,禁止修改!", 8402
		}
	}

	Name, ok := data["Name"]
	if ok && (strings.TrimSpace(Name.(string)) == "") {
		return false, "用户名称不能为空!", 8403 //在同一根部门下,工号必须唯一
	}

	if ok {
		temp := strings.ToLower(strings.TrimSpace(Name.(string)))
		if (temp == "admin") || (temp == "superadmin") {
			return false, "特殊名称,禁止使用!", 8404
		}
	}

	delete(data, "pass") //不允许修改密码

	// Owner, ok := data["owner"]
	// if ok && (strings.TrimSpace(Owner.(string)) == "") {
	// 	data["owner"] = "BaseSystem.LoginUser"
	// }

	loginUserBusinessInfo := GetLoginUserBusinessInfo()
	return common.GetService(loginUserBusinessInfo.DbName, loginUserBusinessInfo.TableName).Edit(ctx, refer, data)
}

/**
 * 删除
 * @param entity 对象类型
 * @param id 记录编号值
 * @param iVersion 记录版本号
 * @return MsgEntity
 */
func (service LoginUserService) Del(ctx *gin.Context, refer *dbinfo.TableInfo, id interface{}, iVersion int) (bool, string, interface{}) {
	if strings.Contains(",00000000,00000001,", ","+id.(string)+",") {
		return false, "特殊用户，禁止删除！", 8101
	}

	info := GetLoginUserBusinessInfo()
	params := map[string]interface{}{
		info.Id: id,
	}

	if info.Version != "" {
		params[info.Version] = iVersion
	}

	var build strings.Builder

	if info.DelSign != "" {
		build.WriteString("UPDATE  ")
		build.WriteString(info.DbName)
		build.WriteString(".")
		build.WriteString(info.TableName)
		build.WriteString(" SET ")
		build.WriteString(info.DelSign)
		build.WriteString(" = 1 ")
	} else {
		build.WriteString("DELETE FROM ")
		build.WriteString(info.DbName)
		build.WriteString(".")
		build.WriteString(info.TableName)

		if info.DelSign != "" {
			build.WriteString(" AND ")
			build.WriteString(info.DelSign)
		}
	}

	build.WriteString(" WHERE ")
	build.WriteString(info.Id)
	build.WriteString(" =  ? ")

	bl, msg, res := sqlfactory.ExecSql(info.DbName, build.String(), id)
	if !bl {
		return bl, msg, res
	}

	if res.(int64) < 1 {
		Log.Error("删除失败,影响值小于1")
		return false, "删除失败", 1002
	}

	return true, "删除成功", 8999
}

/**
 * 修改密码
 * @param ctx
 * @param entity
 * @param sId
 * @param sOldPass
 * @param sNewPass
 * @return MsgEntity
 */
func (service LoginUserService) EditPass(ctx *gin.Context, refer *dbinfo.TableInfo, sId, sOldPass, sNewPass string) (bool, string, interface{}) {
	if sId == "" {
		return false, "用户编号不能为空！", 8001
	}

	if sOldPass == "" {
		return false, "旧密码不能为空！", 8002
	}

	if sNewPass == "" {
		return false, "新密码不能为空！", 8003
	}

	info := GetLoginUserBusinessInfo()

	var build strings.Builder
	build.WriteString("SELECT ")

	if info.State != "" {
		build.WriteString(info.State)
	} else {
		build.WriteString("1")
	}
	build.WriteString(" AS iState, ")

	build.WriteString(info.Pass)
	build.WriteString(" AS sPass, ")

	if info.State != "" {
		build.WriteString(info.Version)
	} else {
		build.WriteString("1")
	}
	build.WriteString(" AS iVersion ")
	build.WriteString(" FROM ")
	build.WriteString(info.DbName)
	build.WriteString(".")
	build.WriteString(info.TableName)
	build.WriteString(" WHERE ")
	build.WriteString(info.Id)
	build.WriteString(" =  ? ")

	if info.DelSign != "" {
		build.WriteString(" AND ")
		build.WriteString(info.DelSign)
		build.WriteString(" = 0 ")
	}

	bl, _, res := sqlfactory.FindOne(build.String(), sId)
	if !bl {
		return false, "没有查找到用户！", 8004
	}

	m := res.(map[string]interface{})
	if m["iState"].(int64) != 1 {
		return false, "用户被限制！", 8007
	}

	appMd5Key := configutil.ReadConfigKey("", "App", "Md5Key", "555").(string)
	sOldPassMd5 := md5util.Lower(sOldPass, appMd5Key)

	if sOldPassMd5 != m["sPass"].(string) {
		return false, "提供的旧密码错误！", 8008
	}

	sNewPassMd5 := md5util.Lower(sNewPass, appMd5Key)
	if sNewPassMd5 == sOldPassMd5 {
		return true, "密码无需修改！", 8999
	}

	loginUserId := moduleutil.CurrentLoginUserId(ctx)
	return service.editPass(sId, sNewPassMd5, sOldPassMd5, loginUserId, m["iVersion"].(int64))
}

func (service LoginUserService) MapToJson(m interface{}, v any) error {
	str, err := json.Marshal(m)
	if err != nil {
		return err
	}

	err = json.Unmarshal(str, v)
	if err != nil {
		return err
	}

	return nil
}

// 重置密码
func (service LoginUserService) ResetPass(ctx *gin.Context, refer *dbinfo.TableInfo, currentUserId, sId, sPass string) (bool, string, interface{}) {
	if sId == "" {
		return false, "用户编号不能为空！", 8001
	}

	if strings.TrimSpace(currentUserId) == "" {
		return false, "未能获取操作人员信息！", 8002
	}

	if ((currentUserId == "00000000") || (currentUserId == "00000001")) && (sId == currentUserId) { //超级管理员登录/管理员或当前用户
		return false, "仅允许管理员或当前用户重置密码", 8003
	}

	info := GetLoginUserBusinessInfo()

	var build strings.Builder
	build.WriteString("SELECT ")

	if info.State != "" {
		build.WriteString(info.State)
	} else {
		build.WriteString("1")
	}
	build.WriteString(" AS iState, ")

	build.WriteString(info.Pass)
	build.WriteString(" AS sPass, ")

	if info.State != "" {
		build.WriteString(info.Version)
	} else {
		build.WriteString("1")
	}
	build.WriteString(" AS iVersion ")
	build.WriteString(" FROM ")
	build.WriteString(info.DbName)
	build.WriteString(".")
	build.WriteString(info.TableName)
	build.WriteString(" WHERE ")
	build.WriteString(info.Id)
	build.WriteString(" =  ? ")

	if info.DelSign != "" {
		build.WriteString(" AND ")
		build.WriteString(info.DelSign)
		build.WriteString(" = 0 ")
	}

	bl, _, res := sqlfactory.FindOne(build.String(), sId)
	if !bl {
		return false, "没有查找到用户！", 8004
	}

	m := res.(map[string]interface{})
	if m["iState"].(int64) != 1 {
		return false, "用户被限制！", 8007
	}

	appMd5Key := configutil.ReadConfigKey("", "App", "Md5Key", "555").(string)
	PassMd5 := md5util.Lower(sPass, appMd5Key)

	if m["sPass"].(string) != PassMd5 {
		return false, "提供的操作密码错误!", 8008
	}

	sNewPass := md5util.Lower("123456", appMd5Key)
	if sNewPass == PassMd5 {
		return true, "密码无需修改重置！", 8999
	}

	return service.resetPass(sId, sNewPass, sId, m["iVersion"].(int64))
}

// 根据用户编号设置用户类型
func (service LoginUserService) EditUserType(ctx *gin.Context, refer *dbinfo.TableInfo, sId, sType string) (bool, string, interface{}) {
	if sId == "" {
		return false, "用户编号不能为空！", 8001
	}

	if strings.TrimSpace(sType) == "" {
		return false, "用户类型不能为空！", 8002
	}

	return service.editUserType(sId, sType)
}

// 设置用户头像
func (service LoginUserService) EditUserHead(ctx *gin.Context, refer *dbinfo.TableInfo, uerId, sHead string) (bool, string, interface{}) {
	if uerId == "" {
		return false, "用户编号不能为空！", 8001
	}

	if strings.TrimSpace(sHead) == "" {
		return false, "图片信息为空！", 8002
	}

	//把base64图片转换为文件
	savePath := "./data/img/head/" + uerId + "/head.png"
	iCode, err := base64util.Base64ToPng(sHead, savePath)
	if err != nil {
		return false, "图片转换失败！", iCode + 7100
	}

	return true, "设置成功！", 8999
}

// 取用户头像
func (service LoginUserService) LookHead(uerId string) (bool, string, interface{}) {
	if uerId == "" {
		return false, "用户编号不能为空！", 8001
	}

	//把base64图片转换为文件
	headPath := "./data/img/head/" + uerId + "/head.png"
	// 读取图片文件
	data, err := os.ReadFile(headPath)
	if err != nil {
		return false, "读取图片文件失败！", 8002
	}

	return true, "读取成功！", data
}

// 修改密码
func (service LoginUserService) editPass(id, newPass, oldPass, modifieder string, iVersion int64) (bool, string, interface{}) {
	info := GetLoginUserBusinessInfo()

	where := map[string]interface{}{
		"id":      id,
		"newPass": newPass,
		"oldPass": oldPass,
	}

	var build strings.Builder
	build.WriteString("UPDATE ")
	build.WriteString(info.DbName)
	build.WriteString(".")
	build.WriteString(info.TableName)
	build.WriteString(" SET ")
	build.WriteString(info.Pass)
	build.WriteString(" =  @newPass, ")

	if info.ModifiedDate != "" {
		build.WriteString(info.ModifiedDate)
		build.WriteString(" = NOW(), ")
	}

	if info.Modifieder != "" {
		build.WriteString(info.Modifieder)
		build.WriteString(" = @modifieder, ")
		where["modifieder"] = modifieder
	}

	if info.Version != "" {
		build.WriteString(info.Version)
		build.WriteString(" = ")
		build.WriteString(info.Version)
		build.WriteString(" +1 ")
	}

	build.WriteString(" WHERE ")
	build.WriteString(info.Id)
	build.WriteString(" = @id ")
	build.WriteString(" AND ")
	build.WriteString(info.Pass)
	build.WriteString(" = @oldPass ")

	if info.Version != "" {
		build.WriteString(" AND ")
		build.WriteString(info.Version)
		build.WriteString(" = @iVersion")
		where[info.Version] = iVersion
	}

	bl, msg, res := sqlfactory.ExecSql(info.DbName, build.String(), where)
	if !bl {
		return bl, msg, res
	}

	if res.(int64) < 1 {
		return false, "数据没有影响值！", 7002
	}

	return true, "更新成功", 7999
}

// 重置密码
func (service LoginUserService) resetPass(id, newPass, modifieder string, iVersion int64) (bool, string, interface{}) {
	info := GetLoginUserBusinessInfo()

	where := map[string]interface{}{
		"id":      id,
		"newPass": newPass,
	}

	var build strings.Builder
	build.WriteString("UPDATE ")
	build.WriteString(info.DbName)
	build.WriteString(".")
	build.WriteString(info.TableName)
	build.WriteString(" SET ")
	build.WriteString(info.Pass)
	build.WriteString(" =  @newPass, ")

	if info.ModifiedDate != "" {
		build.WriteString(info.ModifiedDate)
		build.WriteString(" = NOW(), ")
	}

	if info.Modifieder != "" {
		build.WriteString(info.Modifieder)
		build.WriteString(" = @modifieder, ")
		where["modifieder"] = modifieder
	}

	if info.Version != "" {
		build.WriteString(info.Version)
		build.WriteString(" = ")
		build.WriteString(info.Version)
		build.WriteString(" +1 ")
	}

	build.WriteString(" WHERE ")
	build.WriteString(info.Id)
	build.WriteString(" = @id ")

	if info.Version != "" {
		build.WriteString(" AND ")
		build.WriteString(info.Version)
		build.WriteString(" = @iVersion")
		where[info.Version] = iVersion
	}

	bl, msg, res := sqlfactory.ExecSql(info.DbName, build.String(), where)
	if !bl {
		return bl, msg, res
	}

	if res.(int64) < 1 {
		return false, "数据没有影响值！", 7002
	}

	return true, "更新成功", 7999
}

// 根据用户编号设置用户类型
func (service LoginUserService) editUserType(id, sType string) (bool, string, interface{}) {
	info := GetLoginUserBusinessInfo()

	where := map[string]interface{}{
		"id":    id,
		"sType": sType,
	}

	var build strings.Builder
	build.WriteString("UPDATE ")
	build.WriteString(info.DbName)
	build.WriteString(".")
	build.WriteString(info.TableName)
	build.WriteString(" SET ")
	build.WriteString(info.Type)
	build.WriteString(" =  @sType, ")

	build.WriteString(" WHERE ")
	build.WriteString(info.Id)
	build.WriteString(" = @id ")

	bl, msg, res := sqlfactory.ExecSql(info.DbName, build.String(), where)
	if !bl {
		return bl, msg, res
	}

	if res.(int64) < 1 {
		return false, "数据没有影响值！", 7002
	}

	return true, "更新成功", 7999
}
